package com.kye.express.business.scanner;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.databinding.DataBindingUtil;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Pair;
import android.view.View;
import android.widget.Toast;

import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.jakewharton.rxbinding2.view.RxView;
import com.kye.base.DebounceObservableTransformer;
import com.kye.express.R;
import com.kye.express.business.base.BaseToolbarActivity;
import com.kye.express.business.freight_rates_query.NumberQueryActivity;
import com.kye.express.business.invoice_online.detail.ElectronicInvoiceFragment;
import com.kye.express.business.invoice_online.detail.InvoiceDetailFragment;
import com.kye.express.business.invoice_online.detail.InvoiceDetailListener;
import com.kye.express.business.invoice_online.detail.WaybillListFragment;
import com.kye.express.databinding.ActivityBaseFragmentContainsBinding;
import com.kye.express.databinding.ActivityScannerBinding;
import com.kye.express.view.ToastManager;
import com.kye.rxcodescanner.DecodeFormatManager;
import com.kye.rxcodescanner.RxCodeScanner;
import com.kye.rxcodescanner.RxCodeScannerFragment;
import com.tbruyelle.rxpermissions2.Permission;
import com.tbruyelle.rxpermissions2.RxPermissions;

import java.util.concurrent.TimeUnit;

import io.reactivex.Flowable;
import io.reactivex.Single;
import io.reactivex.SingleObserver;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import io.reactivex.processors.FlowableProcessor;
import io.reactivex.processors.PublishProcessor;
import io.reactivex.schedulers.Schedulers;

/**
 * 扫码
 */
public class ScannerActivity extends BaseToolbarActivity {
    public static final String KEY_SCANNER_RESULT = "scanner_result";
    public static final int RESULT_CODE = 999;
    private static final int REQUEST_CODE_ALBUMS = 1;

    private ActivityScannerBinding mBinding;

    private FlowableProcessor<String> mScanResult = PublishProcessor.<String>create().toSerialized();
    private Disposable mScanResultSubscription;

    private RxPermissions rxPermissions;

    public static void startActivity(Context context) {
        Intent intent = new Intent(context, ScannerActivity.class);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_scanner);
        setUpToolbar((Toolbar) findViewById(R.id.toolbar));
        setTitle(getString(R.string.common_scanner));
        rxPermissions = new RxPermissions(this);
        startScanner();
    }

    private void startScanner() {
        final RxCodeScannerFragment rxCodeScannerFragment = RxCodeScanner.scanFromCamera(
                getSupportFragmentManager(),
                R.id.fragment,
                DecodeFormatManager.CODE_128_AND_QR_CODE_FORMATS
        );

        if (rxCodeScannerFragment != null) {
            rxCodeScannerFragment.setOnCodeScannerListener(new RxCodeScannerFragment.OnCodeScannerListener() {

                @Override
                public void onResultFlowableReady(Flowable<Pair<Result, ReaderException>> flowable) {
                    flowable.observeOn(Schedulers.computation())
                            .filter(new Predicate<Pair<Result, ReaderException>>() {
                                @Override
                                public boolean test(Pair<Result, ReaderException> resultReaderExceptionPair) throws Exception {
                                    return resultReaderExceptionPair.first != null &&
                                            !TextUtils.isEmpty(resultReaderExceptionPair.first.getText());
                                }
                            })
                            .map(new Function<Pair<Result, ReaderException>, String>() {
                                @Override
                                public String apply(Pair<Result, ReaderException> resultReaderExceptionPair) throws Exception {
                                    return resultReaderExceptionPair.first.getText();
                                }
                            })
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(mScanResult);

                    observeScanResult();
                }

                @Override
                public void onOpenTorch(boolean torch) {
                    if (torch) {
                        mBinding.ivLamp.setBackgroundResource(R.drawable.icon_scanner_bg_white);
                        mBinding.ivLamp.setImageResource(R.drawable.icon_scanner_lamp_open);
                        mBinding.tvLamp.setText(getString(R.string.waybill_scanner_close_lamp));
                    } else {
                        mBinding.ivLamp.setBackgroundResource(R.drawable.icon_scanner_bg_black);
                        mBinding.ivLamp.setImageResource(R.drawable.icon_scanner_lamp_close);
                        mBinding.tvLamp.setText(getString(R.string.waybill_scanner_open_lamp));
                    }
                }

                @Override
                public void needOpenTorch(boolean needOpenTorch) {
                    if (!needOpenTorch) {
                        rxCodeScannerFragment.setTorch(false);
                    }
                    mBinding.llLamp.setEnabled(needOpenTorch);
                }

                @Override
                public void onCameraOpened() {
                    Rect rect = mBinding.scanBoxView.getFramingRect();
                    rxCodeScannerFragment.setFocusLocation(rect.centerX(), rect.centerY());
                }
            });
            rxCodeScannerFragment.setContinuousFocus(true);

            RxView.clicks(mBinding.llLamp)
                    .compose(new DebounceObservableTransformer<>())
                    .compose(this.bindToLifecycleDestroy())
                    .subscribe(new Consumer<Object>() {
                        @Override
                        public void accept(Object o) throws Exception {
                            rxCodeScannerFragment.setTorch(!rxCodeScannerFragment.getTorch());
                        }
                    });

            RxView.clicks(mBinding.llAlbums)
                    .compose(new DebounceObservableTransformer<>())
                    .compose(this.bindToLifecycleDestroy())
                    .subscribe(new Consumer<Object>() {
                        @Override
                        public void accept(Object o) throws Exception {
                            selectFromAlbums();
                        }
                    });

            RxView.clicks(mBinding.llAlbums)
                    .compose(new DebounceObservableTransformer<>())
                    .compose(this.bindToLifecycleDestroy())
                    .compose(rxPermissions.ensureEach(Manifest.permission.WRITE_EXTERNAL_STORAGE))
                    .subscribe(new Consumer<Permission>() {
                        @Override
                        public void accept(Permission permission) throws Exception {
                            if (permission.granted) {
                                selectFromAlbums();
                            } else if (permission.shouldShowRequestPermissionRationale) {
                                //TODO
                                showToast("您已经拒绝了权限");
                            } else {
                                //TODO
                                showToast("您已经拒绝了权限");
                            }
                        }
                    });

        }

    }

    private void observeScanResult() {
        mScanResultSubscription = mScanResult
                .subscribe(new Consumer<String>() {

                    @Override
                    public void accept(String s) throws Exception {
                        if (!TextUtils.isEmpty(s)) {
                            setScannerResult(s);
                        } else {
                            observeScanResult();
                        }
                    }
                });
    }

    private void stopObserveScanResult() {
        if (mScanResultSubscription != null && !mScanResultSubscription.isDisposed()) {
            mScanResultSubscription.dispose();
            mScanResultSubscription = null;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopObserveScanResult();
    }

    private void showToast(String message) {
        ToastManager.show(this, message, Toast.LENGTH_SHORT);
    }

    private void selectFromAlbums() {
        Intent i = new Intent(
                Intent.ACTION_PICK,
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(i, REQUEST_CODE_ALBUMS);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (data != null) {
            switch (requestCode) {
                case REQUEST_CODE_ALBUMS:
                    Uri selectedImage = data.getData();
                    if (selectedImage != null) {
                        String[] filePathColumn = {MediaStore.Images.Media.DATA};
                        Cursor cursor = getContentResolver().query(selectedImage,
                                filePathColumn, null, null, null);
                        if (cursor != null) {
                            cursor.moveToFirst();
                            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                            String picturePath = cursor.getString(columnIndex);
                            scannerByPath(picturePath);
                            cursor.close();
                        }
                    }
                    break;
            }
        }
    }

    private void scannerByPath(String imagePath) {
        if (!TextUtils.isEmpty(imagePath)) {
            Single<Result> result = RxCodeScanner.scanFormPath(imagePath, DecodeFormatManager.CODE_128_AND_QR_CODE_FORMATS);
            result.subscribe(new SingleObserver<Result>() {
                @Override
                public void onSubscribe(Disposable d) {
                }

                @Override
                public void onSuccess(Result result) {
                    if (result != null && !TextUtils.isEmpty(result.getText())) {
                        setScannerResult(result.getText());
                    } else {
                        showToast(getString(R.string.waybill_scanner_image_error));
                    }
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                    showToast(getString(R.string.waybill_scanner_image_error));
                }
            });

        } else {
            showToast(getString(R.string.waybill_scanner_image_select_faild));
        }
    }

    private void setScannerResult(String number) {
        stopObserveScanResult();
        Intent intent = new Intent();
        intent.putExtra(KEY_SCANNER_RESULT, number);
        setResult(RESULT_CODE, intent);
        finish();
    }

}
